using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using DictToObject.Factories;
using DictToObject.FieldExpectations;

namespace DictToObject.Builders
{
    public class DictToObjectBuilder<T> : IDictToObjectBuilder<T> where T : new()
    {
        private readonly ICollection<IFieldExpectation> members;
        private readonly IFieldExpectationFactory fieldExpectationFactory;

        public DictToObjectBuilder(IFieldExpectationFactory fieldExpectationFactory)
        {
            this.fieldExpectationFactory = fieldExpectationFactory;
            members = new List<IFieldExpectation>();
        }

        public T Build(IDictionary<string, string> values)
        {
            var result = new T();
            foreach (var fieldExpectation in members)
                fieldExpectation.Apply(result, values);
            return result;
        }

        public IRequiredFieldExpectation AddRequiredField<TField>(string key, Expression<Func<T, TField>> field)
        {
            var memberExpression = (MemberExpression) field.Body;
            IRequiredFieldExpectation fieldExpectation = fieldExpectationFactory.GetRequiredFieldExpectation(key, memberExpression);
            members.Add(fieldExpectation);
            return fieldExpectation;
        }

        public IOptionalFieldExpectation AddOptionalField<TField>(string key, Expression<Func<T, TField>> field, TField defaultValue)
        {
            var memberExpression = (MemberExpression) field.Body;
            IOptionalFieldExpectation fieldExpectation = fieldExpectationFactory.GetOptionalFieldExpectation(key, memberExpression, defaultValue);
            members.Add(fieldExpectation);
            return fieldExpectation;
        }
    }
}